#include "factories.h"
#include <QtXml>
#include <QtCore>

// ObjectFactory implementation

VertexArray* ObjectFactory::createRectangle(Vec3f min, Vec3f max, Color4b color)
{
    VertexArray* rectangle = new VertexArray(4);
    PackedVecColor* vertices = rectangle->getVertices();
    
    SetVec3f(vertices->v, min[0], max[1], min[2]);
    SetColor4b(vertices->c, color);
    vertices++;
    
    SetVec3f(vertices->v, min);
    SetColor4b(vertices->c, color);
    vertices++;
    
    SetVec3f(vertices->v, max[0], min[1], max[2]);
    SetColor4b(vertices->c, color);
    vertices++;
    
    SetVec3f(vertices->v, max);
    SetColor4b(vertices->c, color);
    
    return rectangle;
}


// ColorFactory implementation

Color4b ColorFactory::defaultBackgroundColor = {153, 153, 153, 255};
Color4b ColorFactory::defaultSelectionColor = {255, 255, 255, 255};
Color4b ColorFactory::defaultTextColor = {0, 0, 0, 255};
Color4b ColorFactory::defaultListColor = {255, 255, 255, 255};
Color4b ColorFactory::defaultStateColor = {255, 128, 0, 255};
Color4b ColorFactory::defaultContainerColor = {0, 0, 0, 25};
Color4b ColorFactory::defaultContainerSelectedColor = {0, 0, 255, 25};
Color4b ColorFactory::defaultContainerBorderColor = {255, 255, 255, 50};
Color4b ColorFactory::defaultGridLabelColor = {0, 0, 0, 255};
Color4b ColorFactory::defaultGridBackgroundColor = {255, 255, 255, 255};
Color4b ColorFactory::defaultGridBackgroundBorderColor = {0, 0, 0, 255};

void ColorFactory::setDefaultColors()
{
    SetColor4b(backgroundColor, defaultBackgroundColor);
    SetColor4b(selectionColor, defaultSelectionColor);
    SetColor4b(textColor, defaultTextColor);
	SetColor4b(listColor, defaultListColor);
	SetColor4b(stateColor, defaultStateColor);
	SetColor4b(containerColor, defaultContainerColor);
	SetColor4b(containerSelectedColor, defaultContainerSelectedColor);
	SetColor4b(containerBorderColor, defaultContainerBorderColor);
	SetColor4b(gridLabelColor, defaultGridLabelColor);
	SetColor4b(gridBackgroundColor, defaultGridBackgroundColor);
	SetColor4b(gridBackgroundBorderColor, defaultGridBackgroundBorderColor);
}

void ColorFactory::registerColorKeys()
{
	keyColorMap["ui"]["background"] = &backgroundColor;
	keyColorMap["ui"]["selection"] = &selectionColor;
	keyColorMap["ui"]["text"] = &textColor;
	keyColorMap["ui"]["list"] = &listColor;
	keyColorMap["ui"]["state"] = &stateColor;
	keyColorMap["ui"]["container"] = &containerColor;
	keyColorMap["ui"]["container.selected"] = &containerSelectedColor;
	keyColorMap["ui"]["container.border"] = &containerBorderColor;
	keyColorMap["ui"]["grid.label"] = &gridLabelColor;
	keyColorMap["ui"]["grid.background"] = &gridBackgroundColor;
	keyColorMap["ui"]["grid.background.border"] = &gridBackgroundBorderColor;
}

void ColorFactory::getColor(Color4b out, const QString& category, const QString& key)
{
	if (!keyColorMap[category].contains(key)) {
//		qDebug() << "creating " << key << "in category " << category;
		Color4b* color = new Color4b[1];
		SetColor4b(*color, (unsigned char)255, (unsigned char)255, (unsigned char)255, (unsigned char)255);
		keyColorMap[category][key] = color;
	}
	
	SetColor4b(out, *(keyColorMap[category][key]));
}

void ColorFactory::setColor(Color4b in, const QString& category, const QString& key)
{
	if (!keyColorMap[category].contains(key)) {
//		qDebug() << "creating " << key << "in category " << category;
		Color4b* color = new Color4b[1];
		SetColor4b(*color, (unsigned char)255, (unsigned char)255, (unsigned char)255, (unsigned char)255);
		keyColorMap[category][key] = color;
	}
	
	SetColor4b(*(keyColorMap[category][key]), in);
}

void ColorFactory::saveColorProfile(const QString& path) const
{
	QDomDocument doc("eCosmosColorProfile");
	QDomElement root = doc.createElement("profile");
	doc.appendChild(root);
	
	QMapIterator<QString, QMap<QString, Color4b*> > categoryIter(keyColorMap);
	while (categoryIter.hasNext()) {
		categoryIter.next();
		
		QDomElement category = doc.createElement("category");
		category.setAttribute("key", categoryIter.key());
		root.appendChild(category);
		
		QMapIterator<QString, Color4b*> bindingIter(categoryIter.value());
		while (bindingIter.hasNext()) {
			bindingIter.next();
			
			QDomElement binding = doc.createElement("binding");
			binding.setAttribute("key", bindingIter.key());
			category.appendChild(binding);
			
			Color4b* bindingColor = bindingIter.value();
			QDomElement color = doc.createElement("color");
			color.setAttribute("r", (*bindingColor)[0]);
			color.setAttribute("g", (*bindingColor)[1]);
			color.setAttribute("b", (*bindingColor)[2]);
			color.setAttribute("a", (*bindingColor)[3]);
			binding.appendChild(color);
		}
	}
	
	QFile xmlFile(path);
	if (!xmlFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
		qDebug() << "Couldn't create a color profile save file with path" << path;
		return;
	}
	
	QTextStream* out = new QTextStream(&xmlFile);
	doc.save(*out, 2);
	delete out;
	
	qDebug() << "Saved color profile to path" << path;
}

void ColorFactory::loadColorProfile(const QString& path)
{
	QFile xmlFile(path);
	if (!xmlFile.exists())
		return;
	
	if (!xmlFile.open(QIODevice::ReadOnly | QIODevice::Text))
		return;
	
	QDomDocument doc;
    QString errorStr;
    int errorLine;
    int errorColumn;
    if (!doc.setContent(&xmlFile, true, &errorStr, &errorLine, &errorColumn)) {
		qDebug() << QString("Parse error at line %1, column %2:\n%3").arg(errorLine).arg(errorColumn).arg(errorStr);
		return;
	}
	
	QDomNodeList categories = doc.firstChildElement("profile").childNodes();
	for (int c = 0; c < categories.size(); c++) {
		QDomElement category = categories.at(c).toElement();
		QString categoryKey = category.attributeNode("key").value();
		
		QDomNodeList bindings = category.childNodes();
		for (int b = 0; b < bindings.size(); b++) {
			QDomElement binding = bindings.at(b).toElement();
			QString bindingKey = binding.attributeNode("key").value();
			
			QDomElement color = binding.firstChildElement("color");
			Color4b bindingColor = {
				color.attributeNode("r").value().toInt(),
				color.attributeNode("g").value().toInt(),
				color.attributeNode("b").value().toInt(),
				color.attributeNode("a").value().toInt()
			};
			
			qDebug() << "Setting color for " << categoryKey << bindingKey;
			setColor(bindingColor, categoryKey, bindingKey);
		}
	}
	
	qDebug() << "Loaded color profile at path" << path;
}
